﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics.Eventing.Reader;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HslCommunication.Profinet.Keyence;
using HslCommunication.Core;
using System.Threading;
using System.Windows.Forms.VisualStyles;
using Comm;
using HslCommunication;
using Server;
using DBHelper;
using Model;

namespace SortInUi
{
    public partial class Form1 : Form
    {
        private Dictionary<int, string> StuInfo = new Dictionary<int, string>() { [0] = "空闲中", [1] = "触发扫码", [2] = "放行中", [3] = "动作中", [201] = "放行完成", [301] = "推出完成" };
        private Dictionary<int, string> CtlInfo = new Dictionary<int, string>() { [0] = "无命令", [1] = "1", [3] = "推出", [2] = "放行" };

        private static readonly string CellLine1SqlStr = SysCfg.CellLine1_ConnString;
        private static readonly string CellLine2SqlStr = SysCfg.CellLine2_ConnString;
        private static readonly string AiFuDbStr = SysCfg.TasksDb_ConnString;

        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            PlcHelper.MsgConnectionStatus += PlcHelper_MsgConnectionStatus;
            GetPlan();
        }

        private void PlcHelper_MsgConnectionStatus(string arg1, bool arg2)
        {
            if (arg2 == true)
            {
                lblStu.SetColor(Color.Green);
                lblStu.SetTxt("PLC通信成功");
            }
            else
            {
                lblStu.SetColor(Color.Red);
                lblStu.SetTxt("PLC通信失败");
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text == "启动成功")
            {
                return;
            }
            Logger.WriteSysLog("启动成功");
            ScansHelper.Init();
            PlcHelper.InitPlc();
            PlcHelper.PushTagValEvent += PlcHelper_PushTagValEvent;
            PlcHelper.MsgErrEvent += PlcHelper_MsgErrEvent;
            btnStart.Text = "启动成功";
        }

        private void PlcHelper_MsgErrEvent(string obj)
        {

        }

        private void PlcHelper_PushTagValEvent(string arg1, int arg2)
        {
            Logger.WritePlcLog($"收到PLC数值地址【{arg1}】数值【{arg2}】");
            FreshCtlInfo(arg1, arg2);  //根据变量刷新界面的显示信息

            #region 上线扫码枪控制部分
            if (arg1 == "Scan0Stu" && arg2 == 1 && PlcHelper.GetPlcAddrs().FirstOrDefault(p => p.NO == "InLineEnable")?.AddrValue == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan0");
                scanServer.OnScannedEvent += Scan_OnScannedEvent0;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
                return;
            }
            if (arg1 == "Scan0Stu" && (arg2 == 0 || arg2 == 201 || arg2 == 301))
            {
                var rlt = PlcHelper.SetTag("Scan0Ctl", 0);
                if (!rlt.IsSuccess)
                {
                    string msg = $"写变量【Scan0Ctl】数值【0】失败，原因{rlt.Message}";
                    Msg(msg);
                    Logger.WritePlcLog(msg);
                }
                return;
            }
            #endregion

            #region 一线分流扫码枪
            if (arg1 == "Scan1Stu" && arg2 == 1 && PlcHelper.GetPlcAddrs().FirstOrDefault(p => p.NO == "Line1Enable")?.AddrValue == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan1");
                scanServer.OnScannedEvent += Scan_OnScannedEvent1;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
            }
            if (arg1 == "Scan1Stu" && (arg2 == 0 || arg2 == 201 || arg2 == 301))
            {
                var rlt = PlcHelper.SetTag("Scan1Ctl", 0);
                if (!rlt.IsSuccess)
                {
                    string msg = $"写变量【Scan1Ctl】数值【0】失败，原因{rlt.Message}";
                    Msg(msg);
                    Logger.WritePlcLog(msg);
                }
            }
            #endregion

            #region 二线分流扫码枪
            if (arg1 == "Scan2Stu" && arg2 == 1 && PlcHelper.GetPlcAddrs().FirstOrDefault(p => p.NO == "Line2Enable")?.AddrValue == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan2");
                scanServer.OnScannedEvent += Scan_OnScannedEvent2;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
            }
            if (arg1 == "Scan2Stu" && (arg2 == 0 || arg2 == 201 || arg2 == 301))
            {
                var rlt = PlcHelper.SetTag("Scan2Ctl", 0);
                if (!rlt.IsSuccess)
                {
                    string msg = $"写变量【Scan2Ctl】数值【0】失败，原因{rlt.Message}";
                    Msg(msg);
                    Logger.WritePlcLog(msg);
                }
            }
            #endregion
        }

        private void ScanServer_ScanedErrEvent(string obj)
        {
            Msg(obj);
            Logger.WriteScanLog(obj);
        }
        private void Scan_OnScannedEvent0(string arg1, string arg2)
        {
            Msg(arg1 + "收到条码" + arg2);
            scan0Bar.SetTxt(arg2);
            t_FlowResult flowResult = DbContext.GetModel<t_FlowResult>(AiFuDbStr, $"meterID='{arg2}' order by processDate desc ");
            if (flowResult == null)
            {
                string errMsg = $"查询{arg2}的flowResult失败，不能正常上线";
                Msg(errMsg);
                Logger.WriteSysLog(errMsg);
            }
            else
            {
                var rlt = PlcHelper.SetTag("Scan0Ctl", 2);
                if (rlt.IsSuccess)
                {
                    string msg = $"{arg2}结论合格，能正常上线";
                    Msg(msg);
                    Logger.WriteResultLog(msg);
                }
                else
                {
                    string msg = $"PLC 写数据【Scan0Ctl】数值【2】失败,失败原因是{rlt.Message}";
                    Msg(msg);

                }
            }
        }
        private void Scan_OnScannedEvent1(string arg1, string arg2)
        {
            Msg(arg1 + "收到条码" + arg2);
            scan1Bar.SetTxt(arg2);
            t_Plan cellPlan = DbContext.GetModel<t_Plan>(CellLine1SqlStr, "device_group='组装段'");
            if (cellPlan == null)
            {
                Msg("Cell 一线查询计划失败");
                Logger.WriteSysLog("Cell 一线查询计划失败");
                return;
            }

            t_FlowResult flowResult = DbContext.GetModel<t_FlowResult>(AiFuDbStr, $"meterID='{arg2}'order by processDate desc ");
            if (flowResult == null)
            {
                string info = $"查询{arg2}的flowResult失败，请检查";
                Msg(info);
                Logger.WriteSysLog(info);
                return;
            }

            //var tsk = DbContext.GetModels<t_taskAssemble>(AiFuDbStr,
            //    $"pcbaMaterialID ='{flowResult.meterID}' and productLineID ='QC-FA-CELL-01' and scheduleTime>'{DateTime.Today}'");
            var tsk = DbContext.GetModels<t_taskAssemble>(AiFuDbStr,
                $"pcbaMaterialID ='{flowResult.materialID}' and productLineID ='QC-FA-CELL-01'");
            if (tsk == null)
            {
                string info = $"查询{arg2}的制令信息失败，请检查";
                Msg(info);
                Logger.WriteSysLog(info);
                return;
            }
            if (tsk?.Count(p => p.MaterialId == cellPlan.materiel_code) > 0)
            {
                var rlt = PlcHelper.SetTag("Scan1Ctl", 3);
                if (rlt.IsSuccess)
                {
                    Msg($"{arg2}在一线组装");
                    WriteResult(arg2, cellPlan, "Cell一线");
                }
                else
                {
                    string msg = $"PLC写数据【Scan1Ctl】数值【3】失败，失败原因【{rlt.Message}】";
                    Msg(msg);
                }
            }
            else
            {
                var rlt = PlcHelper.SetTag("Scan1Ctl", 2);
                if (rlt.IsSuccess)
                {
                    Msg($"{arg2}不在一线组装");
                }
                else
                {
                    string msg = $"PLC写数据【Scan1Ctl】数值【3】失败，失败原因【{rlt.Message}】";
                    Msg(msg);
                }

            }

            #region 按照厂内码号段进行验证  旧方法 未用
            //todo 做厂内码进行验证
            //if (innercode < taskAssemble.InnerEnd && innercode > taskAssemble.InnerBegin)
            //{
            //    PlcHelper.SetTag("Scan1Ctl", 1);
            //    Msg($"{innercode}在一线组装");
            //}
            //else
            //{
            //    PlcHelper.SetTag("Scan1Ctl", 2);
            //    Msg($"{innercode}不在一线组装");
            //}
            #endregion

        }
        private void Scan_OnScannedEvent2(string arg1, string arg2)
        {
            Msg(arg1 + "收到条码" + arg2);
            scan2Bar.SetTxt(arg2);
            t_Plan cellPlan = DbContext.GetModel<t_Plan>(CellLine2SqlStr, "device_group='组装段'");
            if (cellPlan == null)
            {
                Msg("Cell 二线查询计划失败");
                return;
            }
            t_FlowResult flowResult = DbContext.GetModel<t_FlowResult>(AiFuDbStr, $"meterID='{arg2}' order by processDate desc ");
            if (flowResult == null)
            {
                Msg($"查询{arg2}的flowResult失败，请检查");
                return;
            }

            var tsk = DbContext.GetModels<t_taskAssemble>(AiFuDbStr,
                $"pcbaMaterialID ='{flowResult.materialID}' and productLineID ='QC-FA-CELL-01'");

            if (tsk?.Count(p => p.MaterialId == cellPlan.materiel_code) > 0)
            {
                var rlt = PlcHelper.SetTag("Scan2Ctl", 3);
                if (rlt.IsSuccess)
                {
                    Msg($"{arg2}在二线组装");
                    WriteResult(arg2, cellPlan, "Cell二线");
                }
                else
                {
                    string msg = $"PLC写数据【Scan2Ctl】数值【3】失败，失败原因【{rlt.Message}】";
                    Msg(msg);
                }

            }
            else
            {
                var rlt = PlcHelper.SetTag("Scan2Ctl", 2);
                if (rlt.IsSuccess)
                {
                    Msg($"{arg2}不在二线组装");
                }
                else
                {
                    string msg = $"PLC写数据【Scan2Ctl】数值【3】失败，失败原因【{rlt.Message}】";
                    Msg(msg);
                }

            }

            #region 按照厂内码号段进行验证  旧方法 未用
            //todo 做厂内码进行验证
            //if (innercode < taskAssemble.InnerEnd && innercode > taskAssemble.InnerBegin)
            //{
            //    PlcHelper.SetTag("Scan2Ctl", 1);
            //}
            //else
            //{
            //    PlcHelper.SetTag("Scan2Ctl", 2);
            //}
            #endregion


        }
        private void Msg(string msg)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (txtMsg.Lines.Length > 100)
                {
                    txtMsg.Clear();
                }
                txtMsg.AppendText($"【{DateTime.Now}】" + msg + Environment.NewLine);
                txtMsg.ScrollToCaret();
            }));
        }
        private void GetPlan()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    List<object> plans = new List<object>();
                    var cellLine1Plan = DbContext.GetModel<t_Plan>(CellLine1SqlStr, "device_group ='组装段'");
                    if (cellLine1Plan != null)
                    {
                        var plan1 = new { 线体名称 = "Cell一线", 制令编号 = cellLine1Plan.workorder_code, 物料号 = cellLine1Plan.materiel_code, };
                        plans.Add(plan1);
                    }
                    var cellLine2Plan = DbContext.GetModel<t_Plan>(CellLine2SqlStr, "device_group ='组装段'");
                    if (cellLine2Plan != null)
                    {
                        var plan2 = new { 线体名称 = "Cell二线", 制令编号 = cellLine2Plan.workorder_code, 物料号 = cellLine2Plan.materiel_code, };
                        plans.Add(plan2);
                    }
                    var cellLine3Plan = DbContext.GetModel<t_Plan>(CellLine2SqlStr, "device_group ='组装段'");
                    if (cellLine3Plan != null)
                    {
                        var plan3 = new { 线体名称 = "Cell三线", 制令编号 = cellLine3Plan.workorder_code, 物料号 = cellLine3Plan.materiel_code, };
                        plans.Add(plan3);
                    }


                    this.BeginInvoke(new Action(() =>
                    {
                        dgvPlan.DataSource = null;
                        dgvPlan.DataSource = plans;
                    }));
                    Thread.Sleep(5000);
                }
            });

        }

        private void btnScanLine1_Click(object sender, EventArgs e)
        {
            var rlt = PlcHelper.GetTagVal("Scan1Stu");
            if (rlt.IsSuccess && rlt.Content == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan1");
                scanServer.OnScannedEvent += Scan_OnScannedEvent1;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
            }
            else if (rlt.IsSuccess)
            {
                Msg("扫码枪1不具备重新扫码条件");
            }
            else
            {
                Msg("通信失败" + rlt.ToMessageShowString());
            }
        }

        private void btnScanLine2_Click(object sender, EventArgs e)
        {
            var rlt = PlcHelper.GetTagVal("Scan2Stu");
            if (rlt.IsSuccess && rlt.Content == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan2");
                scanServer.OnScannedEvent += Scan_OnScannedEvent2;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
            }
            else if (rlt.IsSuccess)
            {
                Msg("扫码枪2不具备重新扫码条件");
            }
            else
            {
                Msg("通信失败" + rlt.ToMessageShowString());
            }
        }

        private void FreshCtlInfo(string arg1, int arg2)
        {
            string name = arg1;
            int val = arg2;
            try
            {
                if (name == "Scan0Stu")
                {
                    Scan0Stu.SetTxt(StuInfo[arg2]);
                }
                if (name == "Scan0Ctl")
                {
                    Scan0Ctl.SetTxt(CtlInfo[val]);
                }

                if (name == "Scan1Stu")
                {
                    Scan1Stu.SetTxt(StuInfo[val]);
                }
                if (name == "Scan1Ctl")
                {
                    Scan1Ctl.SetTxt(CtlInfo[val]);
                }

                if (name == "Scan2Stu")
                {
                    Scan2Stu.SetTxt(StuInfo[val]);
                }
                if (name == "Scan2Ctl")
                {
                    Scan2Ctl.SetTxt(CtlInfo[val]);
                }
            }
            catch (Exception e)
            {
                Logger.WriteSysLog($"根据变量【{name}】数值【{val}】设置信息失败", e);
            }
        }

        private void txtMsg_DoubleClick(object sender, EventArgs e)
        {
            txtMsg.Clear();
        }

        private void btnScanInLine_Click(object sender, EventArgs e)
        {
            var rlt = PlcHelper.GetTagVal("Scan0Stu");
            if (rlt.IsSuccess && rlt.Content == 1)
            {
                ScansHelper scanServer = new ScansHelper();
                scanServer.TrigScan("Scan0");
                scanServer.OnScannedEvent += Scan_OnScannedEvent1;
                scanServer.ScanedErrEvent += ScanServer_ScanedErrEvent;
            }
            else if (rlt.IsSuccess)
            {
                Msg("上线不具备重新扫码条件");
            }
            else
            {
                Msg("通信失败" + rlt.ToMessageShowString());
            }
        }

        private void WriteResult(string barcode, t_Plan planinfo, string Line)
        {
            Logger.WriteResultLog($"厂内码【{barcode}】的工件在{Line}线进行装配，{Line}线的制令号【{planinfo.workorder_code}】、物料号【{planinfo.materiel_code}】");
        }

        private void btnLineCfg_Click(object sender, EventArgs e)
        {
            var view = CfgFrm.GetView();
            view.Show();
            view.Focus();
        }
    }

    public static class Ext
    {
        public static void SetTxt(this Control ctl, string txt)
        {
            if (ctl == null || ctl.IsDisposed || ctl.IsHandleCreated == false)
            {
                return;
            }

            if (ctl.InvokeRequired)
            {
                ctl.BeginInvoke(new Action(() => { ctl.Text = txt; }));
            }
            else
            {
                ctl.Text = txt;
            }
        }
        public static void SetColor(this Control ctl, Color color)
        {
            if (ctl == null || ctl.IsDisposed || ctl.IsHandleCreated == false)
            {
                return;
            }

            if (ctl.InvokeRequired)
            {
                ctl.BeginInvoke(new Action(() => { ctl.BackColor = color; }));
            }
            else
            {
                ctl.BackColor = color;
            }
        }
    }
}
